package com.egg.common.context.util;

import cn.hutool.core.util.ObjectUtil;
import com.egg.common.core.constant.CoreConstant;
import com.egg.common.util.HttpServletUtil;
import io.seata.core.context.RootContext;
import lombok.extern.slf4j.Slf4j;

import javax.servlet.http.HttpServletRequest;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 本地线程存储
 *
 * @author east
 */
@Slf4j
public class LocalThreadContextUtils {


    private static final ThreadLocal<Map<String, Object>> LOCAL_CONTEXT = new ThreadLocal<>();

    private static Map<String, Object> getLocalMap() {
        Map<String, Object> map = LOCAL_CONTEXT.get();
        if (map == null) {
            map = new ConcurrentHashMap<>();
            LOCAL_CONTEXT.set(map);
        }
        return map;
    }

    private static void set(String key, Object value) {
        Map<String, Object> map = getLocalMap();
        map.put(key, value);
    }

    private static Object get(String key) {
        Map<String, Object> map = getLocalMap();
        return map.get(key);
    }

    private static void remove(String key) {
        if (ObjectUtil.isEmpty(key)) {
            return;
        }
        Map<String, Object> map = getLocalMap();
        map.remove(key);
    }

    /**
     * 用户ID
     * -- 初次从网关上下文过滤器中获取，后去从请求头依次向后传递
     *
     * @see com.egg.common.swagger.param.child.SwaggerUserId
     */
    public static final String USER_ID_KEY = "user-id-header";

    public static Long getUserId() {
        Long userId;
        try {
            Object obj = get(USER_ID_KEY);
            if (null == obj) {
                userId = CoreConstant.DEFAULT_ID;
            } else {
                userId = Long.parseLong(obj.toString());
            }
        } catch (Exception e) {
            userId = CoreConstant.DEFAULT_ID;
        }
        return userId;
    }

    public static void setUserId() {
        HttpServletRequest request = HttpServletUtil.getHttpServletRequest();
        setUserId(request);
    }

    public static void setUserId(final HttpServletRequest request) {
        if (null == request) {
            return;
        }
        Long userId = CoreConstant.DEFAULT_ID;
        try {
            userId = Long.parseLong(request.getHeader(LocalThreadContextUtils.USER_ID_KEY));
        } catch (Exception e) {
        }
        setUserId(userId);
    }

    public static void setUserId(Long userId) {
        if (null == userId) {
            userId = CoreConstant.DEFAULT_ID;
        }
        set(USER_ID_KEY, userId);
    }

    public static void removeUserId() {
        remove(USER_ID_KEY);
    }


    /**
     * 用户ID
     * -- 初次从网关上下文过滤器中获取，后去从请求头依次向后传递
     *
     * @see com.egg.common.swagger.param.child.SwaggerDataPerm
     */
    public static final String DATA_PERM_KEY = "data-perm-header";

    public static String getDataPerm() {
        String dataPerm;
        try {
            Object obj = get(DATA_PERM_KEY);
            if (null != obj) {
                dataPerm = obj.toString();
            } else {
                dataPerm = CoreConstant.DEFAULT_ID.toString();
            }
        } catch (Exception e) {
            dataPerm = CoreConstant.DEFAULT_ID.toString();
        }
        return dataPerm;
    }

    public static void setDataPerm() {
        HttpServletRequest request = HttpServletUtil.getHttpServletRequest();
        setDataPerm(request);
    }

    public static void setDataPerm(final HttpServletRequest request) {
        if (null == request) {
            return;
        }
        String dataPerm;
        try {
            dataPerm = request.getHeader(LocalThreadContextUtils.DATA_PERM_KEY);
        } catch (Exception e) {
            dataPerm = CoreConstant.DEFAULT_ID.toString();
        }
        setDataPerm(dataPerm);
    }

    public static void setDataPerm(String dataPermJoin) {
        if (null == dataPermJoin) {
            return;
        }
        set(DATA_PERM_KEY, dataPermJoin);
    }

    public static void removeDataPerm() {
        remove(DATA_PERM_KEY);
    }

    /**
     * seata 传递
     * -- 否则分布式事务会失效
     */
    public static void setSeata() {
        HttpServletRequest request = HttpServletUtil.getHttpServletRequest();
        setSeata(request);
    }

    public static void setSeata(final HttpServletRequest request) {
        try {
            String keyXidHeader = request.getHeader(RootContext.KEY_XID);
            RootContext.bind(keyXidHeader);
        } catch (Exception e) {
            log.error("设置上下文 seata 失败 ", e);
        }
    }

    public static void removeSeata() {
        RootContext.unbind();
    }

    /**
     * 设置所有上下文数据
     */
    public static void setAll() {
        HttpServletRequest request = HttpServletUtil.getHttpServletRequest();
        setAll(request);
    }

    /**
     * 设置所有上下文数据
     */
    public static void setAll(final HttpServletRequest request) {
        setUserId(request);
        setDataPerm(request);
        setSeata(request);
    }

    /**
     * 重置所有上下文数据
     */
    public static void removeAll() {
        removeUserId();
        removeDataPerm();
        removeSeata();
    }


}